﻿
using System.Collections.Generic;


using Corona.TagToolkit.Exception;
namespace Corona.TagToolkit
{
    /// <summary>
    /// Query的查询机制是基于
    /// </summary>
    public class Query
    {
        internal Query()
        {
        }

        private Dictionary<Tag, Pair<long, long>> tagWeightPair;

        private double relevance = 1;

        /// <summary>
        /// 相关度
        /// </summary>
        public double Relevance
        {
            get { return relevance; }
            set
            {
                if (value >= 0 && value <= 1)
                    relevance = value;
                else if (value < 0)
                    relevance = 0;
                else
                    relevance = 1;
            }
        }

        /// <summary>
        /// Pair中第一个为类型的权重，第二个为标签的权重
        /// </summary>
        public Dictionary<Tag, Pair<long, long>> TagWeightPair
        {
            get { return tagWeightPair; }
            set { tagWeightPair = value; }
        }
        /// <summary>
        /// 将标签、权值对用","隔开，标签和其权值用"*"隔开
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            string query = "";
            Dictionary<Tag, Pair<long, long>>.KeyCollection tagKeys = tagWeightPair.Keys;
            foreach (Tag tag in tagKeys)
            {
                Pair<long, long> weigthPair = new Pair<long, long>();
                if (tagWeightPair.TryGetValue(tag, out weigthPair))
                {
                    query += tag.Name + "*" + 
                        (tag.Name==null? "0": weigthPair.A.ToString())
                        + ":" + tag.Value + "*" + weigthPair.B.ToString() + ",";
                }
            }

            query += relevance.ToString();
            return query;
        }

        /// <summary>
        /// 已重载，查询字串相等
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            Query query = obj as Query;
            if (query != null)
                return this.ToString() == query.ToString();
            else
                return false;
        }

        public override int GetHashCode()
        {
            return this.ToString().GetHashCode();
        }
    }

    public class QueryFactory
    {
        private static string criticalName;

        /// <summary>
        /// weakLink中权重最大的name
        /// </summary>
        internal static string CriticalName
        {
            get
            {
                if (criticalName == null)
                    throw new AppSupportNotReadyException("criticalName not init");
                return QueryFactory.criticalName;
            }
            set { QueryFactory.criticalName = value; }
        }


        double relevance = 1;
        WeightVector nameWeightVector;
        public QueryFactory(WeightVector nameWeightVector, double relevance)
        {
            this.relevance = relevance;
            this.nameWeightVector = nameWeightVector;
        }
        /// <summary>
        /// 全功能查询，类型和标签可乘不同的权重
        /// </summary>
        /// <param name="TagWeightPair"></param>
        /// <returns></returns>
        public static Query CreateQuery(Dictionary<Tag, Pair<long, long>> tagWeightPair, double relevance)
        {
       
            Query query = new Query();
            query.TagWeightPair = tagWeightPair;
            query.Relevance = relevance;

            return query;
        }
        public static Query CreateQuery(Dictionary<Tag, long[]> tagWeightlongPair, double relevance)
        {

            Query query = new Query();
            Dictionary<Tag, Pair<long, long>> tagWeightPair = new Dictionary<Tag, Pair<long, long>>();
            Dictionary<Tag, long[]>.KeyCollection tagKeys = tagWeightlongPair.Keys;
            foreach (Tag tag in tagKeys)
            {
                long[] weightPair = new long[2];
                if (tagWeightlongPair.TryGetValue(tag, out weightPair))
                {
                    tagWeightPair.Add(tag, new Pair<long, long>(weightPair[0], weightPair[1]));
                }
                else
                {
                    //抛出异常：几乎不可能发生的错误。。。
                }
            }
            query.TagWeightPair = tagWeightPair;
            query.Relevance = relevance;

            return query;
        }
        /// <summary>
        /// 用于创建与类型无关的查询
        /// 相当于类型的权重为0
        /// </summary>
        /// <param name="tags"></param>
        /// <param name="weights"></param>
        /// <returns></returns>
        public static Query CreateQueryWithWeightedValue(IEnumerable<Tag> tags, IEnumerable<long> weights, double relevance)
        {
            Query query = new Query();
            Dictionary<Tag, Pair<long, long>> tagWeightPair = new Dictionary<Tag, Pair<long, long>>();
            IEnumerator<Tag> tagIter = tags.GetEnumerator();
            IEnumerator<long> weightIter = weights.GetEnumerator();
            while (tagIter.MoveNext() && weightIter.MoveNext())
            {
                tagWeightPair.Add(tagIter.Current, new Pair<long, long>(0, weightIter.Current));
            }

            query.TagWeightPair = tagWeightPair;
            query.Relevance = relevance;
            return query;
        }
        /// <summary>
        /// 类型的权重已在工厂中给定
        /// 相当于类型和标签乘以相同的权重
        /// 将使用工厂的relevance
        /// </summary>
        /// <param name="tags"></param>
        /// <returns></returns>
        public Query CreateQueryWithWeightedName(IEnumerable<Tag> tags)
        {
            return CreateQueryWithWeightedName(tags, relevance);
        }

        public Query CreateQueryWithWeightedName(IEnumerable<Tag> tags, double relevance)
        {

            Query query = new Query();
            Dictionary<Tag, Pair<long, long>> tagWeightPair = new Dictionary<Tag, Pair<long, long>>();
            foreach (Tag tag in tags)
            {
                long weight;
                if (nameWeightVector.TryGetValue(tag.Name, out weight))
                {
                    tagWeightPair.Add(tag, new Pair<long, long>(weight, weight));
                }
                else
                {
                    //抛出异常：几乎不可能发生的错误。。。
                }
            }
            query.TagWeightPair = tagWeightPair;
            query.Relevance = relevance;

            return query;
        }

    }
}
